package br.org.bertol.mestrado;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.CountDownLatch;

import br.org.bertol.mestrado.engine.EngineHillClimbing;
import br.org.bertol.mestrado.engine.Objective;
import br.org.bertol.mestrado.engine.optimisation.hillclimbing.Operador;
import br.org.bertol.mestrado.engine.search.Greedy;
import br.org.bertol.mestrado.util.Configurator;

public class StarterHillClibing extends Starter<EngineHillClimbing> {

    protected StarterHillClibing(Configurator configurator) {
        super(configurator);
    }

    @Override
    public void startEngine() throws InterruptedException {
        for (boolean best_first : new boolean[] { true, false })
            startHillClimbingEngineBySystem(new Greedy(best_first),
                                            configurator.getIteracoes(),
                                            configurator.getSourcePath(),
                                            best_first);
    }

    /**
     * @param greedy
     * @param avalia
     *            ��es
     * @param sourePath
     * @param best_first
     * @throws InterruptedException
     */
    public void startHillClimbingEngineByTypeGreedy(Greedy greedy,
            int avaliacoes, String sourePath, final boolean best_first)
            throws InterruptedException {
        startHillClimbingEngineBySystem(greedy, avaliacoes, sourePath,
                                        best_first);
    }

    /**
     * @param greedy
     * @param avalia
     *            ��es
     * @param sourePath
     * @param best_first
     * @throws InterruptedException
     */
    public void startHillClimbingEngineBySystem(final Greedy greedy,
            final int avaliacoes, final String sourePath,
            final boolean best_first) throws InterruptedException {
        for (String system : configurator.getSystems())
            startHillClimbingEngineByInput(greedy, avaliacoes, sourePath,
                                           system, best_first);
    }

    /**
     * @param greedy
     * @param avalia
     *            ��es
     * @param sourcePath
     * @param system
     * @param best_first
     * @throws InterruptedException
     */
    public void startHillClimbingEngineByInput(final Greedy greedy,
            final int avaliacoes,
            final String sourcePath, final String system,
            final boolean best_first) throws InterruptedException {
        for (Objective[] objectives : configurator.getObjectives())
            startHillClimbingEngineByOperador(objectives, greedy, avaliacoes,
                                              sourcePath, system, best_first);
    }

    /**
     * @param constranint
     * @param greedy
     * @param avalia
     *            ��es
     * @param sourcePath
     * @param system
     * @param best_first
     * @throws InterruptedException
     */
    public void startHillClimbingEngineByOperador(
            final Objective[] constranint, final Greedy greedy,
            final int avaliacoes,
            final String sourcePath, final String system,
            final boolean best_first) throws InterruptedException {
        for (Operador operacao : configurator.getOperacao())
            startHillClimbingEngine(constranint, greedy, operacao, avaliacoes,
                                    sourcePath, system, best_first);
    }

    /**
     * @param constranint
     * @param greedy
     * @param opera
     *            ��o
     * @param avalia
     *            ��es
     * @param sourcePath
     * @param system
     * @param best_first
     * @throws InterruptedException
     */
    public void startHillClimbingEngine(final Objective[] constranint,
            final Greedy greedy, final Operador operacao,
            final int avaliacoes, final String sourcePath, final String system,
            final boolean best_first) throws InterruptedException {
        final CountDownLatch Systemstart = new CountDownLatch(1);

        final CountDownLatch Systemstop = new CountDownLatch(1);

        final EngineHillClimbing engineHillClimbing = new EngineHillClimbing(
                Systemstart, Systemstop,
                avaliacoes, constranint, sourcePath, system, operacao, greedy,
                best_first);

        // start a thread
        engineHillClimbing.start();

        // notifica threads que
        // buscas podem iniciar
        Systemstart.countDown();

        // coloca sistema em modo de espera
        // pela conclus�o das buscas
        Systemstop.await();

        // adiciona na lista de solu��es
        engineList.add(engineHillClimbing);
    }

    @Override
    public void save() throws IOException {

        final String fileName = configurator.getSourcePath() + "/"
                + configurator.getOutPutFile();

        final PrintWriter outFile = new PrintWriter(new BufferedWriter(
                new FileWriter(fileName, true)));

        outFile.println("RESULTADO HILLCLIMBING");

        for (EngineHillClimbing engineHillClimbing : engineList) {
            engineHillClimbing.writeToFile(outFile);
        }

        outFile.close();
    }
}
